package com.googlecode.horncomb.web.util;

import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.NestedNullException;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;

public class TagUtils
{
    protected static final Log logger = LogFactory.getLog(TagUtils.class);

    /**
     * parse query string. split into name-values map from url after '?'
     * @param query
     * @param encoding
     * @return
     * @throws UnsupportedEncodingException
     */
    public static Map<String, String[]> parseQueryString(String query,
            String encoding) throws UnsupportedEncodingException
    {
        if (!StringUtils.hasText(query))
        {
            return new HashMap<String, String[]>();
        }
        String[] params = query.split("&");
        Map<String, String[]> map = new HashMap<String, String[]>();
        for (String param : params)
        {
            String[] nvPare = param.split("=");
            if (nvPare == null || nvPare.length == 0) continue;

            String name = nvPare[0];
            String value = nvPare.length == 1 ? null : URLDecoder.decode(
                    nvPare[1], encoding);
            String[] paramVals = null;
            if (map.containsKey(name))
            {
                paramVals = (String[]) ArrayUtils.add(map.get(name), value);
            }
            else
            {
                paramVals = new String[] { value };
            }
            map.put(name, paramVals);
        }
        return map;
    }

    public static String buildQueryString(Map<String, String[]> parameters,
            String encoding)
    {
        StringBuilder sb = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String[]> entry : parameters.entrySet())
        {
            try
            {
                String key = entry.getKey();
                if (!StringUtils.hasText(key))
                {
                    continue;
                }

                for (String val : entry.getValue())
                {
                    sb.append(first ? "" : "&").append(key).append("=")
                            .append(
                                    val == null ? "" : URLEncoder.encode(val,
                                            encoding));
                    first = false;
                }
            }
            catch (UnsupportedEncodingException e)
            {
                logger.warn(e);
            }
        }
        return sb.toString();
    }

    /**
     * 解析分拆字符串为集合
     * @param idStr
     * @return
     */
    public static Set<String> splitIdString(String idStr)
    {
        final Set<String> ids = new HashSet<String>();
        final String[] idAry = StringUtils
                .commaDelimitedListToStringArray(idStr);

        for (String id : idAry)
        {
            id = id.trim();
            id = StringUtils.replace(id, "\t", "");
            id = StringUtils.replace(id, "\r", "");
            id = StringUtils.replace(id, "\n", "");
            id = StringUtils.replace(id, "\f", "");

            ids.add(id);
        }

        return ids;
    }

    /**
     * 根据传入的bean集合与要获取的属性名，返回属性值的集合
     * @param beans Beans whose property is to be extracted
     * @param name Possibly indexed and/or nested name of the property to be
     * extracted
     * @return the value set of the specified property of the specified bean set
     */
    public static Set<String> parseIdString(Collection<Object> beans,
            String name)

    {
        return parseIdString(beans.iterator(), name);
    }

    public static Set<String> parseIdString(Iterator<Object> iter, String name)
    {
        final Set<String> ids = new HashSet<String>();
        if (iter == null) return ids;
        while (iter.hasNext())
        {
            try
            {
                ids.add(BeanUtils.getProperty(iter.next(), name));
            }
            catch (IllegalAccessException e)
            {
                logger.debug("忽略属性读取错误：" + e.toString());
            }
            catch (InvocationTargetException e)
            {
                logger.debug("忽略属性读取错误：" + e.toString());
            }
            catch (NoSuchMethodException e)
            {
                logger.debug("忽略属性读取错误：" + e.toString());
            }
            catch (NestedNullException e)
            {
                logger.debug("忽略属性读取错误：" + e.toString());
            }
        }
        return ids;
    }

    /**
     * 将Collection转化为以keyPropertyName为key的Map
     * @param beans
     * @param keyPropertyName
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Map convertToMap(Collection beans, String keyPropertyName)
    {
        HashMap map = new HashMap();
        for (Object o : beans)
        {
            try
            {
                map.put(BeanUtils.getProperty(o, keyPropertyName), o);
            }
            catch (IllegalAccessException e)
            {
                logger.debug("忽略属性读取错误：" + e.toString());
            }
            catch (InvocationTargetException e)
            {
                logger.debug("忽略属性读取错误：" + e.toString());
            }
            catch (NoSuchMethodException e)
            {
                logger.debug("忽略属性读取错误：" + e.toString());
            }
        }
        return map;
    }

}
